package com.framework.bdf4j.comm.web;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.framework.bdf4j.comm.download.DownLoader;
import com.framework.bdf4j.comm.download.DownLoaderSimpleFactory;
import com.framework.bdf4j.comm.download.LocalFileDownLoader;
import org.apache.commons.io.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.framework.bdf4j.comm.Constants;
import com.framework.bdf4j.comm.util.FileUtils;
import com.framework.bdf4j.comm.util.R;
import com.framework.bdf4j.comm.util.StringUtils;
import com.framework.bdf4j.comm.util.TreeUtils;
import com.framework.bdf4j.sysadm.entity.SysUser;
import com.framework.bdf4j.sysadm.entity.SysWelcome;
import com.framework.bdf4j.sysadm.service.SysFileService;
import com.framework.bdf4j.sysadm.service.SysMenuService;
import com.framework.bdf4j.sysadm.service.SysUserService;
import com.framework.bdf4j.sysadm.service.SysWelcomeService;
import com.framework.bdf4j.sysadm.vo.MenuVO;
import com.google.code.kaptcha.Producer;

import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * <b>文件名： </b>CommonController.java<br/>
 * <b>类描述： </b>公共视图控制器<br/>
 */
@Controller
@Slf4j
@AllArgsConstructor
@Api(tags = "通用模块")
public class CommonController {

	@Resource(name = "captchaProducer")
	private Producer captchaProducer;

	@Resource(name = "captchaProducerMath")
	private Producer captchaProducerMath;

	private final SysWelcomeService sysWelService;
	private final SysMenuService sysMenuService;
	 private final SysUserService userService;
	 private final SysFileService sysFileService;

	/**
	 * 首页
	 */
	@GetMapping("/index")
	public String goIndex() {
		return "index";
	}

	// 切换主题
	@GetMapping("/switchSkin")
	public String switchSkin(ModelMap mmap) {
		return "home/skin";
	}

	@GetMapping("/register")
	public String goRegister() {
		return "home/register";
	}

	@GetMapping("/forgetPwd")
	public String forgetPwd() {
		return "home/forgetPwd";
	}

	/**
	 * 验证码
	 */
	@GetMapping("/captcha")
	public void kaptcha(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ServletOutputStream out = null;
		try {
			HttpSession session = request.getSession();
			response.setDateHeader("Expires", 0);
			response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
			response.addHeader("Cache-Control", "post-check=0, pre-check=0");
			response.setHeader("Pragma", "no-cache");
			response.setContentType("image/jpeg");

			String type = request.getParameter("type");
			String capStr = null;
			String code = null;
			BufferedImage bi = null;
			if ("math".equals(type)) {
				String capText = captchaProducerMath.createText();
				capStr = capText.substring(0, capText.lastIndexOf("@"));
				code = capText.substring(capText.lastIndexOf("@") + 1);
				bi = captchaProducerMath.createImage(capStr);
			} else if ("char".equals(type)) {
				capStr = code = captchaProducer.createText();
				bi = captchaProducer.createImage(capStr);
			}
			session.setAttribute(Constants.KAPTCHA_SESSION_KEY, code);
			out = response.getOutputStream();
			ImageIO.write(bi, "jpg", out);
			out.flush();

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (out != null) {
					out.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	@ResponseBody
	@PostMapping(value = "/sessiondata/{sessionkey}")
	public String saveSessionData(@PathVariable String sessionkey) {
		String re = "";
		WebUtil.setHttpSession(sessionkey, null);
		return re;
	}

	@ResponseBody
	@RequestMapping(value = "/invalidSession")
	public R invalidateSession(HttpServletRequest reqeust, HttpServletResponse response) {
		String ajaxHeader = reqeust.getHeader("X-Requested-With");
		boolean isAjax = "XMLHttpRequest".equals(ajaxHeader);
		if (isAjax) {
			return R.ok("sessiontimeout");
		} else {
			try {
				response.sendRedirect(reqeust.getContextPath() + "/index");
				return null;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return R.ok();
	}

	// 登出
	@GetMapping("/logout")
	public String logout() {
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		if (auth != null) {
			new SecurityContextLogoutHandler().logout(WebUtil.getRequest(), WebUtil.getResponse(), auth);
		}
		return "redirect:/index";
	}

	/**
	 * main页
	 */
	@GetMapping("/page/main")
	public String main(ModelMap mmap) {
		List<MenuVO> menus = new ArrayList<MenuVO>();
		if (WebUtil.getHttpCurrentUserId() != null) {
			// 查询当前用户所有分配了权限的菜单
			Set<MenuVO> all = new HashSet<>();
			WebUtil.getHttpCurrentRoles().forEach(roleId -> all.addAll(sysMenuService.findMenuByRoleId(roleId)));
			List<MenuVO> menuTreeList = all.stream().filter(menuVo -> Constants.MENU.equals(menuVo.getType()))
					.sorted(Comparator.comparingInt(MenuVO::getSort)).collect(Collectors.toList());
			menus = TreeUtils.getChildPerms(menuTreeList, Constants.MENU_TREE_ROOT_ID);
		}
		mmap.put("menus", menus);
	    SysUser user = userService.selectUserVoById(WebUtil.getHttpCurrentUserId());
        if (StringUtils.isNotEmpty(user.getAvatar())) {
            user.setAvatar(sysFileService.getFileUrl(user.getAvatar()));
        }
        mmap.put("user", user);
		return "home/main";
	}

	/**
	 * dashboard页
	 */
	@GetMapping("/page/dashboard")
	public String dashboard(ModelMap mmap) {
		Integer userId = WebUtil.getHttpCurrentUserId();
		List<SysWelcome> wels = sysWelService.list(Wrappers.<SysWelcome>query().lambda()
				.eq(SysWelcome::getUserId, userId).orderByAsc(SysWelcome::getSort));
		mmap.put("welcomes", wels);
		return "home/dashboard";
	}

	/**
	 * 404页
	 */
	@GetMapping("/page/404")
	public String error404() {
		return "error/404";
	}

	/**
	 * 500页
	 */
	@GetMapping("/page/500")
	public String error500() {
		return "error/500";
	}

	/**
	 * error页
	 */
	@GetMapping("/page/error")
	public String error() {
		return "error/error";
	}

	/**
	 * 修改密码页
	 */
	@GetMapping("/page/goModifyPwd")
	public String modifypwd() {
		return "home/modifypwd";
	}

	/**
	 * 通用下载请求
	 * 
	 * @param fileName 文件名称
	 * @param delete   是否删除
	 * @throws Exception
	 */
	@GetMapping("common/download")
	public void fileDownload(String fileName, Boolean delete, HttpServletResponse response,
			HttpServletRequest request) {

		//首先做response对象设置，考虑到会用两种方式去尝试
		if (!FileUtils.isValidFilename(fileName)) {
			log.error("文件名称非法，不允许下载。 ");
		}
		// 首先解析fileName的后缀名,因为上面已经判断了文件名称不非法，因此直接解析
		String suffix = fileName.substring(fileName.lastIndexOf('.') + 1, fileName.length());

		//根据后缀名获取下载器
		DownLoader downLoader = DownLoaderSimpleFactory.getDownLoader(suffix);

		if(downLoader == null) {
			//写了一个默认的下载器
			downLoader = new LocalFileDownLoader();
		}

		//设置不同浏览器对文件名称显示的兼容问题
		try {
			downLoader.download(fileName,request,response);
		}catch (IOException ex) {
			log.error("文件下载失败",ex);
		}

	}
}